package core

import (
	"fmt"
	"io"
	"os"
	"time"

	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gopkg.in/natefinch/lumberjack.v2"
)

// LoggerParam 日志参数结构体
type LoggerParam struct {
	Path       string `json:"path"        toml:"path"`       // 日志文件路径
	InfoName   string `json:"info_name"   toml:"infoName"`   // Info日志文件名
	ErrorName  string `json:"error_name"  toml:"errorName"`  // 错误日志名
	MaxSize    int    `json:"max_size"    toml:"maxSize"`    // 每个日志最大存储大小
	MaxBackups int    `json:"max_backups" toml:"maxBackups"` // 日志文件最多备份数
	MaxAge     int    `json:"max_age"     toml:"maxAge"`     // 日志文件最大存储天数
	Compress   bool   `json:"compress"    toml:"compress"`   // 是否压缩
}

func (log *LoggerParam) New() *zap.SugaredLogger {
	encoderConfig := zapcore.EncoderConfig{
		TimeKey:       "time",
		LevelKey:      "level",
		NameKey:       "log",
		CallerKey:     "lineNo",
		MessageKey:    "msg",
		StacktraceKey: "stacktrace",
		LineEnding:    zapcore.DefaultLineEnding,
		EncodeLevel:   zapcore.LowercaseLevelEncoder,
		EncodeTime: func(time time.Time, encoder zapcore.PrimitiveArrayEncoder) {
			encoder.AppendString(time.Format("[2006-01-02 15:04:05]"))
		},
		EncodeDuration: zapcore.SecondsDurationEncoder,
		EncodeCaller:   zapcore.FullCallerEncoder, // 全路径编码器
		EncodeName:     zapcore.FullNameEncoder,
	}

	infoLevel := zap.LevelEnablerFunc(func(level zapcore.Level) bool {
		return level < zapcore.WarnLevel && level >= zap.InfoLevel
	})

	errorLevel := zap.LevelEnablerFunc(func(level zapcore.Level) bool {
		return level >= zapcore.WarnLevel && level >= zap.InfoLevel
	})

	core := zapcore.NewTee(
		zapcore.NewCore(zapcore.NewConsoleEncoder(encoderConfig), zapcore.AddSync(log.getWrite(log.InfoName)), infoLevel),
		zapcore.NewCore(zapcore.NewConsoleEncoder(encoderConfig), zapcore.AddSync(log.getWrite(log.ErrorName)), errorLevel),
		// json log
		// zapcore.NewCore(zapcore.NewJSONEncoder(encoderConfig), zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout)), zap.InfoLevel),
		// console log
		zapcore.NewCore(zapcore.NewConsoleEncoder(encoderConfig), zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout)), zap.InfoLevel),
	)

	caller := zap.AddCaller()

	development := zap.Development()
	return zap.New(core, caller, development, zap.Fields()).Sugar()
}

// 获取输出文件io
func (log *LoggerParam) getWrite(fileName string) io.Writer {
	return &lumberjack.Logger{
		Filename:   fmt.Sprintf("%s/%s", log.Path, fileName),
		MaxSize:    log.MaxSize,    // 每个日志最大存储大小
		MaxBackups: log.MaxBackups, // 日志文件最多备份数
		MaxAge:     log.MaxAge,     // 日志文件最大存储天数
		Compress:   log.Compress,   // 是否压缩
	}
}
